//////////////////////////////////////////////////////////////////////////
//                                                                      //
// xrd-dm                                                               //
//                                                                      //
// Author: Martin Vala (SASKE Slovakia and JINR, Russia, 2009)          //
//                                                                      //
// A xrdcp-like command line tool for copying from alien                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#ifndef __XrdDownloadManager_H__
#define __XrdDownloadManager_H__

#define XRDDOWNLOADMANAGER_MAX_SERVERS 10000
#define XRDDOWNLOADMANAGER_MAX_FILES 1000

#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
#include <gapiUI.h>
class XrdDMSimulator;
#include "XrdDMLog.hh"
#include <XrddmConfig.h>
#ifdef HAS_APPMON
#include "XrdDownloadManagerAppMon.hh"

#endif

class XrdDownloadManager {

public:

    enum EDebugLevel {
        kSilent=0,kMoreInfo=1,kDebug=2,kDebugMore=3,kFull=4
    };

    XrdDownloadManager();
    ~XrdDownloadManager();

    void		Init();
	void		InitLogFile();
    void		Reset();
    void		ResetServersFileData();
    int			ReadConfigFile ( string cfgName="xrd-dm.cfg" );
    void		PrintXrddmOptions();
    void 		PrintDownloadInfo();

    void		SetFileIOFileNames ( string in, string out );

    int			ConnectToAliEn();
    int			AddFileToDownloadFromAliEn ( string filename );

    void		SetTimeSeed() {srand ( time ( NULL ) ); };

    void		SetDebug ( int level ) { fDebugLevel = level;fLog.SetDebug(level);;}
    int			GetDebug() { return fDebugLevel;}
    string		GetServerFileFullPath ( string fileprefix="" );
    int			ReadServersFile();
    void		DeleteServersFile();
    void		AddFileToDownload ( string filename,bool isFileStaged=true );
    int			DownloadFile ();

    void		UseFallbackDownload ( bool val=true ) { fUseFallbackDownload = val;};
    void		UseServersFile ( bool val=true ) { fUseServersFile = val;};
    void		UseServersFileTryNewSitesFirst ( bool val=true ) { fUseServersFileTryNewSitesFirst = val;};
    void		UseMonalisa ( bool val=true ) { fUseMonalisa = val;};
    void		UseAliEnCp ( bool val=true ) { fUseAliEnCp = val;};

    int 		DoFallBackDownload();
    int 		DoUseServersFile();
    int 		DoOneDownload ( int index=0 );
    int 		DoAliEnToken ( bool showProcess = true );

    void		SetSimulator ( XrdDMSimulator *sim ) { fSimulator = sim; };

    void		SetXrdCpOptions ( string opt ) { fXrdCpOptions = opt;}
    void		SetXrdCpOptionsExtra ( string opt ) { fXrdCpOptionsExtra = opt;}
    void		GetFileSize ( string filename );
    void		SetConfigOptions ( string var, string val );

    void		CreateAliEnToken ( bool doAlienToken=true ) {fDoAliEnToken = doAlienToken;};
    void		SetAliEnUserName ( string username ) { fAliEnUserName = username;}
    void		SetRenewCertificateTime ( unsigned int time_s ) { fRenewCertificateTime = time_s;}
    void		SetLogDir ( string logdir="/tmp" ) { fLogDir = logdir;}

    void		SetAppMonConfigFile ( string logdir="monalisa.conf" ) { fAppMonConfigFile = logdir;}
    void		SetAppMonName ( string logdir="ALICE::CAF::SE_xrddm" ) { fAppMonName = logdir;}

    int			SetupFileType();

	string		CurrentLogFileName() { return fCurrentLogFileName;}


private:

    GapiUI         *fAliEn;

#ifdef HAS_APPMON
    XrdDownloadManagerAppMon  fAppMon;
#endif

    int             fDebugLevel;
	XrdDMLog		fLog;

    XrdDMSimulator *fSimulator;

    bool            fDoAliEnToken;
    string          fAliEnUserName;
    string          fAliEnPassword;
    unsigned int    fRenewCertificateTime;
    int             fAliEnConnectRetry;

    int             fSuccessfullDownloadSpeed;

    bool            fUseFallbackDownload;
    bool            fUseServersFile;
    bool            fUseServersFileTryNewSitesFirst;
    bool            fUseMonalisa;
    bool            fUseAliEnCp;

    string          fFileNameFromCopyNice;
    string          fFileNameToCopyNice;

    int             fNumberOfFilesToDownload;
    string          fFileNameToDownload[XRDDOWNLOADMANAGER_MAX_FILES];
    bool            fIsFileStaged[XRDDOWNLOADMANAGER_MAX_FILES];
    string          fFileNameToCopy;

    string          fCurrentFileNameNice;
    double          fCurrentFileSize;
    double          fCurrentFileTime;

    string          fXrdCpOptions;
    string          fXrdCpOptionsExtra;

    string          fAppMonConfigFile;
    string          fAppMonName;

    string          fLogDir;
	string			fCurrentLogFileName;

    // server file part
    string          fServersFileDirName;
    string          fServersFileName;
    int             fNumberOfDataServersInFile;
    int             fNumColumnsInServersFile; // number of columns in servers file
    string          fSFPath[XRDDOWNLOADMANAGER_MAX_SERVERS];
    int             fSFSpeed[XRDDOWNLOADMANAGER_MAX_SERVERS];
    int             fSFAccessNumber[XRDDOWNLOADMANAGER_MAX_SERVERS];

    int             OptimizeServersOrder();
    int             AddServerToServersFile ( string name, int speed, int access=1 );
    void            MoveToPositionOfFilesToDownload ( int pos, int indexFile );
    string          GetFileString ( string fullPath );
    string          GetSiteString ( string fullPath );

    int             CopyXrd ( int index );
    string          ExecUnix ( string cmd );
    int             DoSetAliEnVariables();

    // Authentication: check for token and proxy validity, and renew them
    bool            IsTokenExpiring();
    bool            TokenInit ( bool showProcess );
    bool            IsProxyExpiring();
    bool            ProxyInit ( bool showProcess );

    void            FindAndReplaceString ( string &source, const string find, string replace );

};


// Macro for logging
#if defined(__GNUC__) || defined(__ICC) || defined(__ECC) || defined(__APPLE__)
#define THISFUNC() __FUNCTION__
#elif defined(__HP_aCC) || defined(__alpha) || defined(__DECCXX)
#define FUNCTIONNAME() __FUNC__
#else
#define THISFUNC() "???"
#endif

#define XrdDownloadManagerInfo(STR) fLog.Info("XrdDownloadManager::%s %s",THISFUNC(),(STR)));
#define XrdDownloadManagerOk(STR) fLog.Ok("XrdDownloadManager::%s %s",THISFUNC(),(STR));
#define XrdDownloadManagerWarning(STR) fLog.Warning("XrdDownloadManager::%s %s",THISFUNC(),(STR));
#define XrdDownloadManagerError(STR) fLog.Error("XrdDownloadManager::%s %s",THISFUNC(),(STR));
#define XrdDownloadManagerFatal(STR) fLog.Fatal("XrdDownloadManager::%s %s",THISFUNC(),(STR));
#define XrdDownloadManagerDebugSilent(STR) fLog.Debug(1,"XrdDownloadManager::%s %s",THISFUNC(),(STR));
#define XrdDownloadManagerDebugMedium(STR) fLog.Debug(2,"XrdDownloadManager::%s %s",THISFUNC(),(STR));
#define XrdDownloadManagerDebugFull(STR) fLog.Debug(3,"XrdDownloadManager::%s %s",THISFUNC(),(STR));

#endif // __XrdDownloadManager_H__
